package com.git

import org.eclipse.jgit.api.Git
import org.eclipse.jgit.diff.DiffEntry
import org.eclipse.jgit.diff.RenameDetector
import org.eclipse.jgit.internal.storage.file.FileRepository
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.treewalk.TreeWalk
import java.io.File
import java.text.SimpleDateFormat
import java.util.*

class JGitPack {

    fun gitLog(repoGitDir: String): String? {
        return gitLog(File(repoGitDir))
    }

    fun gitPull(repoGitDir: String): Boolean {
        return gitPull(File(repoGitDir))
    }

    fun gitLog(repoGitDir: File): String? {
        // oss提交数据
        var ossPush: MutableList<String>? = null
        if (!repoGitDir.exists()) {
            println("Error! Not Exists : " + repoGitDir.absolutePath)
        } else {
            showLine("开始查看提交日志")
            val repository: Repository = FileRepository(repoGitDir)
            val git = Git(repository)

            val brannch = repository.branch
            println("当前brannch=" + brannch + " | " + repository.fullBranch)
            // 获取最近的一条提交记录
            val ref = repository.findRef(brannch)
            // 选定一条记录开始查询log
            val log = git.log().add(ref.objectId)
            log.setMaxCount(2) // 最多显示条数
            val allCommitsLater = log.call()
            val iter: Iterator<RevCommit> = allCommitsLater.iterator()

            val simple = SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
            simple.timeZone = TimeZone.getTimeZone(TimeZone.getDefault().id)

            val tw = TreeWalk(repository)
            var commit: RevCommit
            var time: String
            while (iter.hasNext()) {
                showLine("华丽的分隔符")
                commit = iter.next()
                println("提交名字=" + commit.shortMessage)
                println("提交人=" + commit.committerIdent.name)
                time = simple.format(Date(commit.commitTime.toLong() * 1000))
                println("提交时间=$time")
                tw.addTree(commit.tree)
            }

            tw.isRecursive = true
            if (tw.treeCount < 2) {
                System.err.println("无法查询记录")
                return null
            }
            val rd = RenameDetector(repository)
            rd.addAll(DiffEntry.scan(tw))
            val diffEntries = rd.compute()
            if (diffEntries == null || diffEntries.isEmpty()) {
                System.err.println("无法查询记录")
                return null
            }

            val iterator = diffEntries.iterator()
            var diffEntry: DiffEntry
            ossPush = mutableListOf()

            ossPush.add("parent")
            val outFilePath = repoGitDir.parent + "/"
            ossPush.add(outFilePath)

            val deleteOssPush = mutableListOf<String?>()
            val addOssPush = mutableListOf<String?>()
            while (iterator.hasNext()) {
                diffEntry = iterator.next()
                println(
                    "newPath:" + diffEntry.newPath + "    oldPath:"
                            + diffEntry.oldPath + "   changeType:"
                            + diffEntry.changeType
                )

                if (diffEntry.changeType == DiffEntry.ChangeType.DELETE) {
                    deleteOssPush.add(outFilePath + diffEntry.oldPath)
                } else {
                    addOssPush.add(outFilePath + diffEntry.newPath)
                }
            }

            if (deleteOssPush.isNotEmpty()) {
                ossPush.add("deleteFile")
                ossPush.add(deleteOssPush.joinToString(","))
            }
            if (addOssPush.isNotEmpty()) {
                ossPush.add("addFile")
                ossPush.add(addOssPush.joinToString(","))
            }
        }

        return ossPush?.joinToString(" ")
    }

    fun gitStatus(repoDir: File) {
        val RepoGitDir = File(repoDir.absolutePath + "/.git")
        if (!RepoGitDir.exists()) {
//            logger.info("Error! Not Exists : " + RepoGitDir.getAbsolutePath());
        } else {
            var repo: Repository? = null
            try {
                repo = FileRepository(RepoGitDir.absolutePath)
                val git = Git(repo)
                val status = git.status().call()
                println("Git Change: " + status.changed)
                println("Git Modified: " + status.modified)
                println("Git UncommittedChanges: " + status.uncommittedChanges)
                println("Git Untracked: " + status.untracked)
                //                logger.info("Pulled from remote repository to local repository at " + repo.getDirectory());
            } finally {
                repo?.close()
            }
        }
    }

    fun gitCheckout(repoDir: File, version: String) {
        val RepoGitDir = File(repoDir.absolutePath + "/.git")
        if (!RepoGitDir.exists()) {
//            logger.info("Error! Not Exists : " + RepoGitDir.getAbsolutePath());
        } else {
            var repo: Repository? = null
            try {
                repo = FileRepository(RepoGitDir.absolutePath)
                val git = Git(repo)
                val checkout = git.checkout()
                checkout.setName(version)
                checkout.call()

                //                logger.info("Checkout to " + version);
                val pullCmd = git.pull()
                pullCmd.call()

                //                logger.info("Pulled from remote repository to local repository at " + repo.getDirectory());
            } finally {
                repo?.close()
            }
        }
    }

    fun gitClone(remoteUrl: String, repoDir: File?) {
        val git = Git.cloneRepository()
            .setURI(remoteUrl)
            .setDirectory(repoDir)
            .call()
        //            logger.info("Cloning from " + remoteUrl + " to " + git.getRepository());
    }

    /**
     * pull
     * @param repoGitDir .git 路径
     * @return
     */
    fun gitPull(repoGitDir: File): Boolean {
        if (!repoGitDir.exists()) {
            System.err.println("Error! Not Exists : " + repoGitDir.absolutePath)
        } else {
            var repo: Repository? = null
            try {
                repo = FileRepository(repoGitDir.absolutePath)
                val git = Git(repo)
                val pullCmd = git.pull()
                val pu = pullCmd.call()

                if (pu.mergeResult != null) {
                    val mr = pu.mergeResult
                    println(mr.mergeStatus)
                    if ((mr.base as RevCommit).name == (mr.newHead as RevCommit).name) {
                        return false
                    }
                } else {
                    println("No update result")
                }
                return pu.isSuccessful
            } finally {
                repo?.close()
            }
        }
        return false
    }

    private fun showLine(str: String) {
        println("  ******************** $str ********************")
    }
}
